
import { defineAsyncComponent } from 'vue';
let logPre = defineAsyncComponent(() => {
    return new Promise((resolve, reject) => {
        fetch('../../env-static-resources/forWS63E/editor/progress.html')
            .then((res) => res.text())
            .then(template => {
                resolve({
                    template,
                    props: ['data', 'modal'],
                    data() {
                        return {
                            burning: false,
                            percent: 0,
                            fileCnt: 0,
                            fwpkg: null,
                            currentFileCnt: 0,
                            warn: null,
                            serial: null,
                        }
                    },
                    methods: {
                        async stopBurn() {
                            if (!this.burning) {
                                return;
                            }
                            this.burning = false;
                            this.serial?.release();
                        },
                        async startBurn() {
                            this.currentFileCnt = 0;
                            this.percent = 0;
                            if (this.burning) {
                                return;
                            }
                            this.burning = true;
                            let port;
                            let portClosed = false;
                            try {
                                const usbSerialAdapters = [
                                    { usbVendorId: 0x1a86, usbProductId: 0x7522 }, // CH340 serial converter
                                    { usbVendorId: 0x1a86, usbProductId: 0x7523 }, // CH340 serial converter
                                    { usbVendorId: 0x1a86, usbProductId: 0x5523 }, // CH341 serial converter
                                ];
                                try {
                                    port = await navigator.serial.requestPort({ filters: usbSerialAdapters });
                                } catch (e) {
                                    return;
                                }
                                const serial = new WS63Serial(port, this.$refs.pre);
                                this.serial = serial;
                                console.log("Wait for Handshake");
                                this.warn = (OpenBlock.i('请按下开发板上的重置按键'));
                                await serial.reqHandshake(921600);
                                this.warn = null;
                                let fwpkg = this.fwpkg;
                                let fileCnt = this.fileCnt;
                                this.currentFileCnt = 1;
                                await serial.sendFileBuf(
                                    "root_loaderboot_sign.bin",
                                    fwpkg.getBinUint8Buffer("root_loaderboot_sign.bin"),
                                    (serial, total, wrote) => {
                                        this.percent = Math.max(1, wrote / total * 100);
                                        console.log(`Downloading ${~~(wrote / total * 100)}%`);
                                    }
                                );
                                // await serial.reqBaudrate(1000000);
                                for (const binInfo of fwpkg.binl) {
                                    if (!binInfo["type_2"]) continue;
                                    this.currentFileCnt++;
                                    if (binInfo["name"] == "ws63_all_nv.bin") {
                                        continue;
                                    }
                                    if (binInfo["name"] == "ws63_all_nv_backup.bin") {
                                        continue;
                                    }
                                    this.percent = 1;
                                    await serial.reqSendBin(binInfo["burn_addr"], binInfo["length"]);
                                    await serial.sendFileBuf(
                                        binInfo["name"],
                                        fwpkg.getBinUint8Buffer(binInfo["name"]),
                                        (serial, total, wrote) => {
                                            this.percent = Math.max(1, wrote / total * 100);
                                            console.log(`Downloading ${binInfo["name"]}: ${~~(wrote / total)}%`);
                                        }
                                    );
                                    // Wait for MCU, neccesary on some high baudrates.
                                    await new Promise(resolve => setTimeout(resolve, 10));
                                }

                                // await serial.reqReset();
                                await serial.release();
                                portClosed = true;
                            } catch (e) {
                                console.error(e);
                                alert(e.message);
                            } finally {
                                if (!portClosed) {
                                    port?.close();
                                }
                                this.burning = false;
                                this.currentFileCnt = 0;
                                this.percent = 0;
                            }
                        },
                        async downloadHex() {
                            FileOD.Save(this.data.filename, this.data.file);
                        },
                        cancel() {
                            try {
                                this.serial?.release();
                            } catch (e) { }
                            this.modal.close();
                        },
                        copyLog() {
                            let txt = this.$refs.pre.innerText;
                            console.log(txt);
                            navigator.permissions.query({ name: 'clipboard-write' }).then(function (result) {
                                if (result.state == 'granted' || result.state == 'prompt') {
                                    navigator.clipboard.writeText(txt);
                                    OB_IDE.$Message.success({
                                        background: true,
                                        content: OpenBlock.i('已复制到剪贴板')
                                    });
                                }
                                // Don't do anything if the permission was denied.
                            });
                        }
                    },
                    mounted() {
                        this.fwpkg = new WS63Fwpkg(this.data.file);
                        this.fileCnt = this.fwpkg.binl.length;
                    }
                })
            });
    })
});
export class BurnTool {
    burn(file, scene, filename) {
        OB_IDE.openModal({
            closable: false,
            maskClosable: false,
            title: OpenBlock.i('选择端口'),
            component: logPre,
            componentOptions: {
                file, scene, filename
            }
        });
    }
}